import getpass
import math
import os
import sys
import time
from tkinter import filedialog, simpledialog, messagebox
import tkinter as tk
from playwright.sync_api import sync_playwright
import win32com.client as win32
import datetime
import cv2
import requests
import base64
import usage_logger
import win32timezone    # 不能删

from user_data import send_monitoring_data


# 增加了Excel多选
# 增加了用户使用记录
# 增加了点击Save前先点击其他地方取消日历框，以免遮挡
class AccessTokenManager:
    access_token = None
    token_expires_at = 0

    @staticmethod
    def get_access_token():
        if AccessTokenManager.access_token and time.time() < AccessTokenManager.token_expires_at:
            return AccessTokenManager.access_token

        # 发起获取access token的请求
        client_id = "GbCYhAlxmV2h4FtObMrF9LUz"
        client_secret = "47FGNS8GWov00W7kKgQqyYkFfGMqLOko"
        token_url = rf"https://aip.baidubce.com/oauth/2.0/token?client_id={client_id}&client_secret={client_secret}&grant_type=client_credentials"
        params = {
            "grant_type": "client_credentials",
            "client_id": client_id,
            "client_secret": client_secret
        }
        response = requests.get(token_url, params=params)
        if response.status_code == 200:
            token_data = response.json()
            AccessTokenManager.access_token = token_data["access_token"]
            AccessTokenManager.token_expires_at = time.time() + token_data["expires_in"]
            return AccessTokenManager.access_token
        else:
            raise Exception("Failed to get access token")


def baidu_ocr(page_obj):
    # encoding:utf-8
    request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/numbers"
    # 获取验证码
    element = page_obj.query_selector('#imgValidateCode')
    # 验证码坐标
    bounding_box = element.bounding_box()
    x, y = bounding_box['x'], bounding_box['y']
    # 截取验证码图片
    page_obj.screenshot(path='screenshot.png')
    cropped_image = cv2.imread('screenshot.png')[y:y + 26, x:x + 56]  # 根据实际需要设置裁剪区域的坐标和大小
    # 保存裁剪后的图片
    cv2.imwrite('cropped.png', cropped_image)
    # 替换以下变量为您的图像路径
    image_path = r'cropped.png'

    # 二进制方式打开图片文件
    with open(image_path, 'rb') as f:
        img = base64.b64encode(f.read())
    params = {"image": img}
    access_token = AccessTokenManager.get_access_token()
    # access_token = '24.7166d97b4bb8f63fc738196d89f873aa.2592000.1697965424.282335-36960384'
    request_url = f"https://aip.baidubce.com/rest/2.0/ocr/v1/numbers?access_token={access_token}"
    headers = {'content-type': 'application/x-www-form-urlencoded'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        result = response.json()
        if 'words_result' in result:
            for word in result['words_result']:
                return word['words']
        else:
            print("OCR failed with error code:", result['error_code'])

def prompt_for_captcha():
    root = tk.Tk()
    root.withdraw()
    captcha = simpledialog.askstring("输入验证码", "请输入验证码:")
    return captcha

def select_files():
    root = tk.Tk()
    root.withdraw()
    file_paths = filedialog.askopenfilenames(title="请选择ADEO数据的Excel文件")
    if not file_paths:
        sys.exit()
    return file_paths


def get_earliest_date(sheet):
    last_row = sheet.Cells(sheet.Rows.Count, 1).End(-4162).Row  # 寻找第一列的最后一个非空行
    earliest_date = None
    for row in range(2, last_row):  # 从第二行开始，跳过标题行
        cell_value = sheet.Cells(row, 1).Value
        if cell_value:
            date_value = datetime.datetime.fromtimestamp(cell_value.timestamp())
            if earliest_date is None or date_value < earliest_date:
                earliest_date = date_value
    return earliest_date


def login(page):
    page.locator("#txtUserName").fill("SGS004")
    page.locator("#txtUserPwd").fill("123123")
    # code = baidu_ocr(page)
    code = prompt_for_captcha()
    page.fill("#txtCode", str(code))
    page.get_by_role("button", name="Submit").click()


def enter_qua_for_testing(page):
    page.frame_locator("iframe[name=\"frmleft\"]").locator("#tree_1_switch").click()
    page.frame_locator("iframe[name=\"frmleft\"]").get_by_role("link",
                                                               name="quotation for testing(Lab)").click()


def enter_issue_new_qua(page):
    page.frame_locator("iframe[name=\"frmright\"]").get_by_role("button",
                                                                name="issue new quotation").click()
def close_add_data_iframe(page):
    page.locator("[id^='_ButtonClose_a']").first.click()

def wait_for_frame(page, dia_frame):
    page.set_default_timeout(60000)
    start_time = time.time()
    try:
        page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#aspnetForm").wait_for(state="visible")
    finally:
        end_time = time.time()
        execution_time = end_time - start_time
    return execution_time


def add_data(page, dia_frame, action_QE, file_name, supplierCode, supplierName, earliest_date_str, today_str):
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_ddl_FService_chosen a").click()
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator(
        "#ctl00_ContentPlaceHolder1_ddl_FService_chosen").get_by_text("TCF").click()
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_ddl_TService_chosen a").click()
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator(
        "#ctl00_ContentPlaceHolder1_ddl_TService_chosen").get_by_text("TCF Validation").click()  # service mode
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_servicemodenote").fill(
        "TCF Validation")  # service mode note
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_UserName").fill(
        str(action_QE))  # action_QE
    # page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_DeptName").fill("Quality-SH")
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_quotationnumbernote").fill(
        file_name)  # excel文件名
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_suppliercode").fill(
        str(supplierCode))
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_suppliername").fill(
        supplierName)
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_factorycode").fill(
        str(supplierCode))
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_factoryname").fill(
        supplierName)
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_location").fill("SGS-SH HG")
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_startdate").fill(
        earliest_date_str)
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_finishdate").fill(
        today_str)
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_productdescription").fill(
        "TCF")
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator("#ctl00_ContentPlaceHolder1_txt_modelqty").fill("1")


def price_zone(page, n, dia_frame, eanNo, price):
    page.frame_locator(f"[id=\"{dia_frame}\"]").get_by_role("link", name="Price Zone").click()
    page.frame_locator(f"[id=\"{dia_frame}\"]").get_by_role("button", name="Add test item").click()
    page.frame(name=dia_frame).locator("input[name=\"txt_TestItem\"]").nth(n).fill(str(eanNo))
    page.frame(name=dia_frame).locator("input[name=\"txt_ReferenceClause\"]").nth(n).fill('TCF')
    page.frame(name=dia_frame).locator("input[name=\"txt_Testunitprice\"]").nth(n).fill(str(price))
    page.frame(name=dia_frame).locator("input[name=\"txt_Testqty\"]").nth(n).fill("1")


def add_data_bottom(page, dia_frame):
    # page.frame_locator(f"[id=\"{dia_frame}\"]").locator('#ctl00_ContentPlaceHolder1_txt_Total').fill("1")
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator('#ctl00_ContentPlaceHolder1_txt_taxinspection').click()
    page.frame_locator(f"[id=\"{dia_frame}\"]").locator('#ctl00_ContentPlaceHolder1_txt_quotationamount').click()
    # page.frame_locator(f"[id=\"{dia_frame}\"]").locator('#ctl00_ContentPlaceHolder1_txt_Total').click()


def PO_information_input(page, n, count, dia_frame, matrix_ID, earliest_date_str, today_str, price):
    page.frame_locator(f"[id=\"{dia_frame}\"]").get_by_role("link", name="PO information").click()
    page.frame_locator(f"[id=\"{dia_frame}\"]").get_by_role("button", name="Add order info").click()
    page.frame(name=dia_frame).locator("input[name=\"txt_POnumber\"]").nth(n).fill(matrix_ID)

    page.frame(name=dia_frame).locator("input[name=\"txt_orderqty\"]").nth(n).fill(str(count))

    page.frame(name=dia_frame).locator("input[name=\"txt_inspectiondate\"]").nth(n).fill(earliest_date_str)
    page.frame(name=dia_frame).locator("input[name=\"txt_SRdate\"]").nth(n).fill(today_str)
    page.frame(name=dia_frame).locator("input[name=\"txt_readatet\"]").nth(n).fill(today_str)
    page.frame(name=dia_frame).locator("input[name=\"txt_inspectionAmount\"]").nth(n).fill(str(price))
    page.frame(name=dia_frame).locator("input[name=\"txt_inspectionAmount\"]").nth(n).click()


def get_dict(sheet, last_row):
    # suppliername相同的行合并写入字典
    data_dict = {}
    for i in range(2, last_row + 1):
        matrix_ID = sheet.Cells(i, 2).Value
        action_QE = sheet.Cells(i, 4).Value
        eanNo = int(sheet.Cells(i, 5).Value)
        price = sheet.Cells(i, 6).Value
        supplierName = sheet.Cells(i, 17).Value
        supplierCode = int(sheet.Cells(i, 18).Value)
        reportNo = int(sheet.Cells(i, 3).Value)

        print(supplierCode)
        print('eanNo:', eanNo)
        print('price:', price)
        # eanNo = int(eanNo) if eanNo is not None else 0
        # price = int(price) if price is not None else 0
        # supplierCode = int(supplierCode) if supplierCode is not None else 0

        if supplierName in data_dict:
            data_dict[supplierName].append((matrix_ID, eanNo, price, action_QE, supplierCode, reportNo))
        else:
            data_dict[supplierName] = [(matrix_ID, eanNo, price, action_QE, supplierCode, reportNo)]
    key_value_no = len(data_dict)  # 获取字典长度（suppliername个数）
    print(data_dict)
    return key_value_no, data_dict


def get_Msgbox(page, supplierName):
    selector = '#q_Msgbox'
    element = page.locator(selector)
    content = element.inner_text()

    # 弹出提示框
    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口

    with open("input_log.txt", "a", encoding="utf-8") as f:
        if content == "Save！":
            f.write(rf"供应商：{supplierName}保存成功！" + "\n")
            messagebox.showinfo("任务完成", rf"供应商：{supplierName} 保存成功！")
            page.wait_for_timeout(2000)
        elif content == "the content in red box is not correct, please fill out as required！":
            f.write(rf"存在未填写项或者填写错误！" + "\n")
            messagebox.showwarning("警告", rf"存在未填写项或者填写错误！")
            page.get_by_role("cell", name="Add Data 关闭 最大化").get_by_title("关闭").click()
        else:
            f.write(rf"供应商：{supplierName}" + content + "\n")
            messagebox.showerror("错误", rf"供应商：{supplierName} {content}")
            page.get_by_role("cell", name="Add Data 关闭 最大化").get_by_title("关闭").click()
    root.destroy()

class ADEOInputProcessor:
    def __init__(self):
        self.log_file = "input_log.txt"

    def clear_log_file(self):
        with open(self.log_file, "w") as f:
            f.write("")

    def process_data(self):
        file_paths = select_files()
        self.clear_log_file()

        excel = win32.gencache.EnsureDispatch('Excel.Application')
        excel.DisplayAlerts = False
        excel.Visible = False

        with sync_playwright() as p:
            try:
                browser = p.chromium.launch(headless=False,channel="chrome")  # 使用自动管理的浏览器
            except Exception as e:
                with open("error_log.txt", "w") as f:
                    f.write(str(e))
                raise
            context = browser.new_context(no_viewport=True)
            page = context.new_page()
            page.goto("https://www.adeo-iqc.com/Login.aspx")
            login(page)
            enter_qua_for_testing(page)

            for file_path in file_paths:
                file_name = os.path.basename(file_path)
                file_name_without_extension = os.path.splitext(file_name)[0]
                workbook = excel.Workbooks.Open(file_path, ReadOnly=True)
                sheet = workbook.Worksheets(1)
                last_row = sheet.Cells(sheet.Rows.Count, 1).End(-4162).Row  # 寻找第一列的最后一个非空行
                key_value_no, data_dict = get_dict(sheet, last_row)
                earliest_date = get_earliest_date(sheet)
                earliest_date_str = earliest_date.strftime("%Y-%m-%d")
                today = datetime.date.today()
                today_str = today.strftime("%Y-%m-%d")

                enter_issue_new_qua(page)

                for i in range(1, key_value_no + 1):
                    supplierName = list(data_dict.keys())[i - 1]
                    values = data_dict[supplierName]
                    dia_frame_main = rf"_DialogFrame_a{i}"
                    for m, value in enumerate(values):  # 获取键值对的值数据
                        matrix_ID, eanNo, price, action_QE, supplierCode, reportNo = value
                        if price is not None:
                            if m == 0:
                                n = 0
                                wait_for_frame(page, dia_frame_main)
                                add_data(page, dia_frame_main, action_QE, file_name_without_extension, supplierCode,
                                         supplierName,
                                         earliest_date_str, today_str)
                                price_zone(page, n, dia_frame_main, eanNo, price)
                            else:
                                n = n + 1
                                price_zone(page, n, dia_frame_main, eanNo, price)
                            add_data_bottom(page, dia_frame_main)
                    # 计算B/F/Q列都相同时，计算相同键的次数
                    count_dict = {}
                    for value in values:
                        matrix_ID, eanNo, price, action_QE, supplierCode, reportNo = value
                        key = (supplierName, matrix_ID, price)
                        if price is not None:
                            if key in count_dict:
                                count_dict[key] += 1
                            else:
                                count_dict[key] = 1
                        data = [
                            {
                                "user_name": f"{usage_logger.username}",
                                "user_location": f"{usage_logger.location}",
                                "rpa_id": "121",
                                "rpa_name": "ADEO_InputForTCF",
                                "rpa_version": "0.2",
                                "occurrence": f"{usage_logger.start_time}",
                                "info": "ADEO客户系统自动录入数据",
                                "extra": f"{reportNo}"
                            }
                        ]
                        send_monitoring_data(data)
                    n = 0
                    for key, count in count_dict.items():
                        supplierName, matrix_ID, price = key
                        total_price = price * count
                        PO_information_input(page, n, count, dia_frame_main, matrix_ID, earliest_date_str, today_str,
                                             total_price)
                        n = n + 1

                    page.frame_locator(f"[id=\"{dia_frame_main}\"]").get_by_role("button", name="Save").click()

                    page.wait_for_timeout(1000)
                close_add_data_iframe(page)
            page.close()
            workbook.Close(SaveChanges=False)
            browser.close()
        excel.Quit()


if __name__ == "__main__":
    # 开始时间
    start_time = datetime.datetime.now()
    processor = ADEOInputProcessor()
    processor.process_data()
    messagebox.showinfo("任务完成", "所有任务已成功完成！")
    print("Finished!")
